import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.Arrays;

import com.speljohan.rsbot.accessors.NPC;
import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSItemTile;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class SeerYews extends Script implements PaintListener,
		ServerMessageListener {

	public int treeID = 1309;
	public int bankerID = 495;
	private final int[] nestIds = { 5070, 5071, 5072, 5073, 5074, 5075, 5076,
			7413, 11966 };
	public RSTile[] treesToBankPath = new RSTile[] { new RSTile(2720, 3467),
			new RSTile(2724, 3475), new RSTile(2725, 3490) };
	public RSTile[] bankToTreesPath = new RSTile[] { new RSTile(2725, 3480),
			new RSTile(2722, 3468), new RSTile(2713, 3463) };

	public RSTile tree1Tile = new RSTile(2715, 3460);
	public RSTile tree2Tile = new RSTile(2706, 3465);
	public RSTile bankTile = new RSTile(2727, 3495);
	public RSTile centerTile = new RSTile(2706, 3460);

	public int lvls = 0;
	int loads = 0;
	int yewsCut;
	int chopped;

	public long startTime = System.currentTimeMillis();
	int startingExperience = 0;
	boolean cameraMoving = false;

	public RSTile[] walkBackPath = new RSTile[] { new RSTile(3222, 3216),
			new RSTile(3227, 3234), new RSTile(3218, 3251),
			new RSTile(3199, 3246), new RSTile(3162, 3240),
			new RSTile(3143, 3234), new RSTile(3127, 3222),
			new RSTile(3113, 3224), new RSTile(3102, 3240),
			new RSTile(3103, 3259), new RSTile(3105, 3272),
			new RSTile(3097, 3286), new RSTile(3078, 3282),
			new RSTile(3062, 3275), new RSTile(3042, 3272),
			new RSTile(3024, 3276), new RSTile(3010, 3281),
			new RSTile(3007, 3294), new RSTile(3008, 3312),
			new RSTile(3006, 3344), new RSTile(3001, 3356),
			new RSTile(2998, 3363), new RSTile(2989, 3371),
			new RSTile(2974, 3379), new RSTile(2965, 3394),
			new RSTile(2961, 3410), new RSTile(2951, 3422),
			new RSTile(2946, 3434), new RSTile(2939, 3451),
			new RSTile(2924, 3449), new RSTile(2918, 3433),
			new RSTile(2908, 3419), new RSTile(2891, 3422),
			new RSTile(2875, 3429), new RSTile(2866, 3455),
			new RSTile(2858, 3466), new RSTile(2856, 3480),
			new RSTile(2862, 3494), new RSTile(2855, 3509),
			new RSTile(2841, 3507), new RSTile(2851, 3496),
			new RSTile(2848, 3479), new RSTile(2843, 3468),
			new RSTile(2844, 3459), new RSTile(2853, 3445),
			new RSTile(2842, 3432), new RSTile(2829, 3438),
			new RSTile(2812, 3436), new RSTile(2797, 3433),
			new RSTile(2784, 3442), new RSTile(2778, 3447),
			new RSTile(2773, 3454), new RSTile(2763, 3466),
			new RSTile(2759, 3471), new RSTile(2750, 3474),
			new RSTile(2742, 3476), new RSTile(2727, 2484),
			new RSTile(2725, 3491), new RSTile(2726, 3493) };

	int waitAfterMoving = -1;

	int failCount = 0;

	RSNPC ent;

	int ENT = 0;

	boolean spinningView = false;

	public int antiBan() {
		switch (random(0, 400)) {
		case 0:
			setCameraRotation(random(1, 359));
			break;
		case 1:
			setCameraRotation(random(1, 359));
			break;
		case 2:
			setCameraRotation(random(1, 359));
			break;
		case 3:
			setCameraRotation(random(1, 359));
			break;
		case 4:
			setCameraRotation(random(1, 359));
			break;
		case 5:
			setCameraRotation(random(1, 359));
			break;
		case 6:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 7:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 8:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 9:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 10:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 11:
			moveMouse(random(0, 515), random(0, 337));
			break;
		case 12:
			moveMouse(random(0, 764), random(0, 502));
			break;
		case 13:
			moveMouse(random(0, 764), random(0, 502));
			break;
		case 14:
			moveMouse(random(0, 764), random(0, 502));
			break;
		case 15:
			openTab(Constants.TAB_INVENTORY);
			break;
		case 16:
			openTab(Constants.TAB_INVENTORY);
			break;
		case 17:
			openTab(Constants.TAB_STATS);
			break;
		case 18:
			openTab(Constants.TAB_STATS);
			break;
		case 19:
			openTab(random(0, 13));
			break;
		case 20:
			openTab(random(0, 13));
			break;
		case 21:
			openTab(random(0, 13));
			break;
		default:
			break;
		}
		return random(300, 500);
	}

	public boolean atBank() {
		return distanceTo(bankTile) < 15;
	}

	public boolean attackedByEnt() {
		ent = null;
		ent = getNearestNPCByName("Yew");
		if (ent == null || getMyPlayer().getInteracting() == null) {
			return false;
		}
		return getMyPlayer().getInteracting().equals(ent);
	}

	public boolean atTrees() {
		return distanceTo(tree1Tile) < 10 || distanceTo(tree2Tile) < 10;
	}

	public int bank() {
		if (atBank()) {
			if (RSInterface.getInterface(Constants.INTERFACE_BANK).isValid()) {
				bank.depositAllExcept(1349, 1351, 1353, 1355, 1357, 1359, 6739);
				loads++;
				return random(500, 800);
			} else {
				runOn();
				if (distanceTo(bankTile) > 0) {
					if (dpWalkTile(bankTile)) {
						waitAfterMoving = random(200, 300);
						return random(500, 800);
					} else {
						return -1;
					}
				} else {
					if (useBanker()) {
						return random(500, 800);
					} else {
						return -1;
					}
				}
			}
		} else {
			if (treesToBank()) {
				return random(500, 800);
			} else {
				return -1;
			}
		}
	}

	public boolean bankToTrees() {
		return dpWalkPath(bankToTreesPath);
	}

	public boolean checkAttack() {
		if (getMyPlayer().isInCombat()) {
			return runFromCombat();
		} else {
			return false;
		}
	}

	public boolean checkCamera() {
		if (cameraMoving) {
			if (Bot.getClient().getCameraCurveY() >= 380) {
				Bot.getInputManager().releaseKey((char) KeyEvent.VK_UP);
				cameraMoving = false;
			}
			return true;
		} else if (Bot.getClient().getCameraCurveY() < 380) {
			Bot.getInputManager().pressKey((char) KeyEvent.VK_UP);
			cameraMoving = true;
			return true;
		}
		return false;
	}

	public void checkEnt() {
		ent = null;
		ent = getNearestNPCByName("Yew");
		if (getMyPlayer().getInteracting().equals(ent)) {
			atTile(getMyPlayer().getLocation(), "walk here");
		}
	}

	public boolean checkForEnt() {
		if (getMyPlayer().getInteracting() != null) {
			final int count = Bot.getClient().getNPCCount();
			final NPC[] npcs = Bot.getClient().getNPCArray();
			final int[] ints = Bot.getClient().getNPCIndexArray();
			for (int i = 0; i < count; i++) {
				final RSNPC npc = new RSNPC(npcs[ints[i]]);
				if (getMyPlayer().getInteracting().equals(npc)
						&& Arrays.asList("Yew").contains(npc.getName())) {
					atTile(getMyPlayer().getLocation(), "alk here");
					ENT++;
					return true;
				}
			}
		}
		return false;
	}

	public boolean checkSpinningView() {
		if (spinningView) {
			Bot.getInputManager().releaseKey((char) KeyEvent.VK_RIGHT);
			spinningView = false;
			return true;
		} else {
			return false;
		}
	}

	public int chop() {
		if (atTrees()) {
			final int result = clickTree();
			if (result > 0) {
				if (result == 1) {
					waitAfterMoving = random(500, 800);
				}
				return random(500, 800);
			} else {
				if (result == -1) {
					spinView();
				} else {
					if (distanceTo(centerTile) > 2) {
						final RSTile rCenterTile = new RSTile(centerTile.getX()
								+ random(-1, 1), centerTile.getY()
								+ random(-1, 1));
						dpWalkTile(rCenterTile);
					}
				}
				return random(500, 800);
			}
		} else {
			if (bankToTrees()) {
				return random(500, 800);
			} else {
				return -1;
			}
		}
	}

	public int clickTree() {
		final RSObject object = findObject(treeID);
		if (object == null || distanceTo(object.getLocation()) > 16) {
			return -2;
		}
		if (atObject(object, "Chop")) {
			return 1;
		}
		if (distanceTo(object.getLocation()) > 3) {
			if (dpWalkTile(object.getLocation())) {
				return 2;
			}
		}
		if (getMyPlayer().getAnimation() != -1) {
			return antiBan();
		}
		return -1;
	}

	public boolean dpWalkPath(final RSTile[] path) {
		for (int i = path.length - 1; i >= 0; i--) {
			if (dpWalkTile(path[i])) {
				return true;
			}
		}
		return false;
	}

	public boolean dpWalkTile(final RSTile tile) {
		if (distanceTo(tile) <= 16) {
			walkTileMM(tile);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public String getAuthor() {
		return "Force_";
	}

	@Override
	public String getName() {
		return "Seer Yew's";
	}

	@Override
	public String getScriptCategory() {
		return "Woodcutting";
	}

	@Override
	public String getScriptDescription() {
		String html = "";

		html += "<html>n";
		html += "<body>n";
		html += "<h2>" + getName() + " v" + getVersion() + "</h2><br>n";
		html += "Author: " + getAuthor() + "<br><br>n";
		html += "Chopes at seers village.<br><br>Start anywhere with an axe in your inventory or equipped it will detect if its lotst and teleport to Lumbridge and walk back.";
		html += "</body>n";
		html += "</htmln";

		return html;
	}

	@Override
	public double getVersion() {
		return 1.2;
	}

	public void homeTele() {
		openTab(Constants.TAB_MAGIC);
		castSpell(1);
	}

	public boolean isWelcomeButton() {
		final RSInterface welcomeInterface = RSInterface.getInterface(378);
		if (welcomeInterface.getChild(45).getAbsoluteX() > 20
				|| !welcomeInterface.getChild(117).getText().equals(
						"10.1120.190")
				&& !welcomeInterface.getChild(117).getText().equals("")) {
			log("We still are in Welcome Screen");
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int loop() {

		if (!isLoggedIn()) {
			return random(100, 200);
		}
		if (checkSpinningView()) {
			return random(200, 300);
		}
		if (checkCamera()) {
			return random(500, 800);
		}
		nest();
		if (getMyPlayer().isMoving()) {
			return random(150, 200);
		}
		if (waitAfterMoving != -1) {
			final int toReturn = waitAfterMoving;
			waitAfterMoving = -1;
			return toReturn;
		}
		if (checkAttack()) {
			return random(800, 1000);
		}
		if (getMyPlayer().getAnimation() != -1) {
			return random(150, 200);
		}
		final int result = work();
		if (result != -1) {
			failCount = 0;
			return result;
		}
		if (walkBack()) {
			failCount = 0;
			return random(500, 800);
		}
		if (checkForEnt()) {
			return random(100, 200);
		}
		failCount++;
		if (failCount >= 10) {
			failCount = 0;
			homeTele();
			return random(2000, 3000);
		}
		return random(1000, 2000);
	}

	public void nest() {
		final RSItemTile nest = getGroundItemByID(nestIds);
		if (nest != null) {
			log("Found nest");
			atTile(nest, "Take");
		}
	}

	@Override
	public void onFinish() {
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		long millis = System.currentTimeMillis() - startTime;
		final long hours = millis / (1000 * 60 * 60);
		millis -= hours * 1000 * 60 * 60;
		final long minutes = millis / (1000 * 60);
		millis -= minutes * 1000 * 60;
		final long seconds = millis / 1000;
		if (startingExperience == 0) {
			startingExperience = skills
					.getCurrentSkillExp(Constants.STAT_WOODCUTTING);
		}
		final int gainedExp = skills
				.getCurrentSkillExp(Constants.STAT_WOODCUTTING)
				- startingExperience;

		g.drawString("Runtime: " + hours + "." + minutes + "." + seconds + ".",
				9, 251);
		g.drawString("Levels gained: " + lvls / 2, 9, 267);
		g.drawString("Exp. Gained : " + gainedExp, 9, 283);
		g.drawString("Yews cut : " + yewsCut, 9, 299);
		g.drawString("Loads: " + loads, 9, 315);
	}

	@Override
	public boolean onStart(final String[] args) {
		return true;
	}

	public boolean runFromCombat() {
		if (atBank()) {
			bankToTrees();
			return true;
		}
		if (atTrees()) {
			treesToBank();
			return true;
		}
		return false;
	}

	public void runOn() {
		setRun(true);
	}

	public void serverMessageRecieved(final ServerMessageEvent e) {
		if (e.getMessage().contains("You get some yew logs.")) {
			yewsCut++;
		}
		if (e.getMessage().contains("level")) {
			lvls++;
		}
	}

	public void spinView() {
		Bot.getInputManager().pressKey((char) KeyEvent.VK_RIGHT);
		spinningView = true;
	}

	public boolean treesToBank() {
		return dpWalkPath(treesToBankPath);
	}

	public boolean useBanker() {
		final RSNPC npc = getNearestNPCByID(bankerID);
		return atNPC(npc, "Bank Banker");
	}

	public boolean walkBack() {
		return dpWalkPath(walkBackPath);
	}

	public int work() {
		if (getInventoryCount() != 28) {
			return chop();
		} else {
			return bank();
		}
	}
}